<template>
    <div class="captcha-wrapper">
      <div class="captcha-image-wrapper">
        <img :src="imageUrl" class="captcha-image" />
        <canvas ref="maskCanvas" class="mask-canvas"></canvas>
      </div>
  
      <div class="slider-wrapper">
        <div class="slider-track">
          <div
            class="slider-thumb"
            @mousedown="startDrag"
            :style="{ transform: `rotate(${angle}deg)` }"
          >
            <svg viewBox="0 0 24 24" class="rotate-icon">
              <path d="M4.93 4.93a10 10 0 1 1-1.41 1.41L1 2v6h6L5.34 5.34a8 8 0 1 0 1.41-1.41z" />
            </svg>
          </div>
        </div>
        <div class="status-text">{{ status }}</div>
      </div>
    </div>
  </template>
  
  <script>
  export default {
    name: 'CircularPuzzleCaptcha',
    data() {
      return {
        imageUrl: 'https://images.unsplash.com/photo-1507525428034-b723cf961d3e?w=320',
        radius: 30,
        centerX: 100,
        centerY: 60,
        angle: 0,
        isDragging: false,
        targetAngle: 45 + Math.floor(Math.random() * 270), // 随机目标角度
        status: '请旋转滑块填充拼图',
      };
    },
    mounted() {
      this.drawMaskPiece();
    },
    methods: {
      drawMaskPiece() {
        const canvas = this.$refs.maskCanvas;
        const ctx = canvas.getContext('2d');
        canvas.width = 300;
        canvas.height = 120;
  
        // 清空画布
        ctx.clearRect(0, 0, canvas.width, canvas.height);
  
        // 创建主图遮罩形状
        ctx.save();
        ctx.beginPath();
        ctx.arc(this.centerX, this.centerY, this.radius, 0, Math.PI * 2);
        ctx.clip();
  
        const image = new Image();
        image.crossOrigin = 'anonymous';
        image.src = this.imageUrl;
  
        image.onload = () => {
          ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
          ctx.restore();
        };
      },
      startDrag(e) {
        this.isDragging = true;
        const onMove = (event) => {
          if (!this.isDragging) return;
          const deltaX = event.clientX - e.clientX;
          this.angle = (deltaX / 2) % 360;
        };
  
        const onUp = () => {
          this.isDragging = false;
          document.removeEventListener('mousemove', onMove);
          document.removeEventListener('mouseup', onUp);
          this.verify();
        };
  
        document.addEventListener('mousemove', onMove);
        document.addEventListener('mouseup', onUp);
      },
      verify() {
        const diff = Math.abs(this.angle - this.targetAngle) % 360;
        if (diff < 5 || diff > 355) {
          this.status = '✅ 验证通过';
        } else {
          this.status = '❌ 请再试一次';
        }
      },
    },
  };
  </script>
  
  <style scoped>
  .captcha-wrapper {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 320px;
    background: #1e293b;
    padding: 1rem;
    border-radius: 0.5rem;
  }
  .captcha-image-wrapper {
    position: relative;
    width: 100%;
    height: 120px;
  }
  .captcha-image {
    width: 100%;
    height: 100%;
    border-radius: 0.5rem;
    object-fit: cover;
  }
  .mask-canvas {
    position: absolute;
    top: 0;
    left: 0;
  }
  .slider-wrapper {
    margin-top: 1rem;
    width: 100%;
  }
  .slider-track {
    position: relative;
    height: 2rem;
    background: #e2e8f0;
    border-radius: 1rem;
  }
  .slider-thumb {
    position: absolute;
    top: -0.25rem;
    left: 0;
    width: 2rem;
    height: 2rem;
    background: #3b82f6;
    border-radius: 50%;
    cursor: grab;
    display: flex;
    align-items: center;
    justify-content: center;
  }
  .rotate-icon {
    width: 1.2rem;
    height: 1.2rem;
    fill: white;
  }
  .status-text {
    margin-top: 0.5rem;
    color: #f9fafb;
    font-size: 0.875rem;
    text-align: center;
  }
  </style>
  